/*
 * $Id: log.h 128 2011-10-03 14:39:34Z hyunghwan.chung $
 *
   Copyright 2005-2009 Chung, Hyung-Hwan.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an  BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

#ifndef _XP_UTL_LOG_H_
#define _XP_UTL_LOG_H_

#include <xp/types.h>
#include <xp/macros.h>
#include <xp/bas/mtx.h>
#include <xp/net/socket.h>

/* TODO: improve this and complete win32 portion */

#define XP_LOG_MSG_MAX   10204
#define XP_LOG_IDENT_MAX 32

/*
 * MACROS: target
 * - XP_LOG_CONSOLE
 * - XP_LOG_FILE
 * - XP_LOG_SYSLOG
 * - XP_LOG_SYSLOG_R4 - remote syslog server with an IPv4 address
 */
#define XP_LOG_CONSOLE    (0x0100)
#define XP_LOG_FILE       (0x0200)
#define XP_LOG_SYSLOG     (0x0400)
#define XP_LOG_SYSLOG_R4  (0x0800)

/*
 * MACROS: priority
 * - XP_LOG_PANIC
 * - XP_LOG_ALERT
 * - XP_LOG_CRITICAL
 * - XP_LOG_ERROR
 * - XP_LOG_WARNING
 * - XP_LOG_NOTICE
 * - XP_LOG_INFO
 * - XP_LOG_DEBUG
 */
#define XP_LOG_PANIC    0
#define XP_LOG_ALERT    1
#define XP_LOG_CRITICAL 2
#define XP_LOG_ERROR    3
#define XP_LOG_WARNING  4
#define XP_LOG_NOTICE   5
#define XP_LOG_INFO     6
#define XP_LOG_DEBUG    7

/*
 * MACROS: facility
 */
enum xp_log_fac_t
{
	XP_LOG_KERN     = (0<<3),  /* kernel messages */
	XP_LOG_USER     = (1<<3),  /* random user-level messages */
	XP_LOG_MAIL     = (2<<3),  /* mail system */
	XP_LOG_DAEMON   = (3<<3),  /* system daemons */
	XP_LOG_AUTH     = (4<<3),  /* security/authorization messages */
	XP_LOG_SYSLOGD  = (5<<3),  /* messages from syslogd */
	XP_LOG_LPR      = (6<<3),  /* line printer subsystem */
	XP_LOG_NEWS     = (7<<3),  /* network news subsystem */
	XP_LOG_UUCP     = (8<<3),  /* UUCP subsystem */
	XP_LOG_CRON     = (9<<3),  /* clock daemon */
	XP_LOG_AUTHPRIV = (10<<3), /* authorization messages (private) */
	XP_LOG_FTP      = (11<<3), /* ftp daemon */
	XP_LOG_LOCAL0   = (16<<3), /* reserved for local use */
	XP_LOG_LOCAL1   = (17<<3), /* reserved for local use */
	XP_LOG_LOCAL2   = (18<<3), /* reserved for local use */
	XP_LOG_LOCAL3   = (19<<3), /* reserved for local use */
	XP_LOG_LOCAL4   = (20<<3), /* reserved for local use */
	XP_LOG_LOCAL5   = (21<<3), /* reserved for local use */
	XP_LOG_LOCAL6   = (22<<3), /* reserved for local use */
	XP_LOG_LOCAL7   = (23<<3)  /* reserved for local use */
};

typedef enum xp_log_fac_t xp_log_fac_t;

/*
 * MACRO: XP_LOG_ENABLED
 *
 * PARAMETERS:
 * log - log object
 * pri - one of the <priority> values
 */
#define XP_LOG_ENABLED(log,pri)((pri) <= ((log)->type & 0x00FF)) 

/*
 * MACROS: XP_LOG0 (log,ident,pri,fmt,...)
 *
 * PARAMETERS:
 * log - log object
 * ident - identifier
 * pri - one of the <priority> values
 * fmt - format used by <xp_printf>
 */
#define XP_LOG0(log,ident,pri,fmt) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt); \
	} while (0)

#define XP_LOG1(log,ident,pri,fmt,m1) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1); \
	} while (0)
#define XP_LOG2(log,ident,pri,fmt,m1,m2) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2); \
	} while (0)
#define XP_LOG3(log,ident,pri,fmt,m1,m2,m3) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3); \
	} while (0)
#define XP_LOG4(log,ident,pri,fmt,m1,m2,m3,m4) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4); \
	} while (0)
#define XP_LOG5(log,ident,pri,fmt,m1,m2,m3,m4,m5) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5); \
	} while (0)

#define XP_LOG6(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6); \
	} while (0)

#define XP_LOG7(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7); \
	} while (0)

#define XP_LOG8(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7,m8) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7, m8); \
	} while (0)

#define XP_LOG9(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7,m8,m9) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7, m8, m9); \
	} while (0)

#define XP_LOG10(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10); \
	} while (0)

#define XP_LOG11(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10,m11); \
	} while (0)

#define XP_LOG12(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10,m11,m12); \
	} while (0)
#define XP_LOG13(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,m13) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10,m11,m12,m13); \
	} while (0)
#define XP_LOG14(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,m13,m14) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10,m11,m12,m13,m14); \
	} while (0)
#define XP_LOG15(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,m13,m14,m15) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10,m11,m12,m13,m14,m15); \
	} while (0)


/*
 * TYPE: xp_log_t
 */

struct xp_log_t
{
	int type; 

	struct 
	{
		xp_char_t file[XP_PATH_MAX + 1];
#ifdef _WIN32
		/* TODO: xp_handle_t console;*/
#endif
		struct
		{
			xp_sckadrin4_t host;
			xp_sckhnd_t sock;
		} syslog_r4;
	} target;

	xp_char_t ident[XP_LOG_IDENT_MAX + 1];

	xp_char_t msgbuf[XP_LOG_MSG_MAX + 1];
	xp_char_t msgbuf2[XP_LOG_MSG_MAX + XP_LOG_IDENT_MAX + 50];

#if defined(XP_CHAR_IS_MCHAR)
	/* nothing extra */
#else
	xp_mchar_t msgbuf_mb[XP_LOG_MSG_MAX * 2 + 1];
#endif

	xp_mtx_t mtx;

#ifndef _WIN32
	xp_log_fac_t syslog_facility;
#endif
	xp_bool_t __dynamic;
};

typedef struct xp_log_t xp_log_t;

#ifdef __cplusplus
extern "C" {
#endif

/*
 * FUNCTION: xp_log_open
 * Allocates and/or initializes an xp_log_t object.
 * If *log* is XP_NULL, it allocates a new xp_log_t object.
 *
 * PARAMETERS:
 * x - xxx
 * y - kdsajflkdsj
 *
 * RETURNS:
 * The address of the xp_log_t object allocated or initialized on success
 * XP_NULL in case of insufficient memory
 * 
 * SEE ALSO:
 * <xp_log_open>
 */
xp_log_t* xp_log_open (xp_log_t* log, const xp_char_t* ident, int type, ...);

/*
 * FUNCTION: xp_log_close
 * 
 * PARAMETERS:
 * log - log object
 */
void xp_log_close (xp_log_t* log);

/*
 * FUNCTION: xp_log_clear
 */
int xp_log_clear (xp_log_t* log);

/* 
 * FUNCTION: xp_log_setident
 */
void xp_log_setident (xp_log_t* log, const xp_char_t* ident);

/* 
 * FUNCTION: xp_log_settarget
 */
void xp_log_settarget (xp_log_t* log, int type);

/* 
 * FUNCTION: xp_log_settargetfile
 */
void xp_log_settargetfile (xp_log_t* log, const xp_char_t* file);

/* 
 * FUNCTION: xp_log_settargetsyslogr4host
 */
void xp_log_settargetsyslogr4host (xp_log_t* log, const xp_sckadrin4_t* addr);

/*
 * FUNCTION: xp_log_setpriority
 */
void xp_log_setpriority (xp_log_t* log, int priority);

/*
 * FUNCTION: xp_log_setprioritybyname
 */
int xp_log_setprioritybyname (xp_log_t* log, const xp_char_t* name);

/*
 * FUNCTION: xp_log_setsyslogfacility
 */
void xp_log_setsyslogfacility (xp_log_t* log, xp_log_fac_t facility);

/*
 * FUNCTION: xp_log_setsyslogfacilitybyname
 */
int xp_log_setsyslogfacilitybyname (xp_log_t* log, const xp_char_t* name);

/* 
 * FUNCTION: xp_log_getpriority 
 */
int xp_log_getpriority (xp_log_t* log);

/*
 * FUNCTION: xp_log_getpriorityname
 */
const xp_char_t* xp_log_getpriorityname (xp_log_t* log);

/* 
 * FUNCTION: xp_log_gettarget 
 */
int xp_log_gettarget (xp_log_t* log);

/*
 * FUNCTION: xp_log_report
 */
int xp_log_report (xp_log_t* log, 
	const xp_char_t* ident, int pri, const xp_char_t* fmt, ...);

/*
 * FUNCTION: xp_getlogpriorityname
 */
const xp_char_t* xp_getlogpriorityname (int pri);

#ifdef __cplusplus
}
#endif

#endif
